using Fusion.Frameworks.Assets;
using Fusion.Frameworks.Notification;
using System;
using System.Collections.Generic;
using UnityEngine;

namespace Fusion.Frameworks.UI
{
    /// <summary>
    /// UI运行模式
    /// </summary>
    public enum UILaunchMode
    {
        Standard,   //无论是否有相同的UI，直接创建新的
        SingleTop   //如果有相同的UI，则展示已存在的UI页面，并关闭其上层所有界面。否则创建新的。
    }

    /// <summary>
    /// UI类型
    /// </summary>
    public enum UIType
    {
        Window,     //展示Window UI时，会把上一个Window类型的UI及其上层Pop全部隐藏。
        Pop         //展示Pop UI时，不会隐藏任何UI
    }

    public enum UILifeType
    { 
        Normal,
        Persistent
    }


    /// <summary>
    /// UI页面数据，可以继承UIData，扩展需要传输的数据
    /// </summary>
    public class UIData
    {
        private string name = null;
        private UILaunchMode launchMode = UILaunchMode.Standard;

        private GameObject gameObject;

        public UIData()
        {
        }

        public UIData(UILaunchMode launchMode)
        {
            this.launchMode = launchMode;
        }

        public UILaunchMode LaunchMode { get => launchMode; set => launchMode = value; }
        public string Name { get => name; set => name = value; }
        public GameObject GameObject { get => gameObject; set => gameObject = value; }
    }

    /// <summary>
    /// UI页面对象
    /// 所有UI必须继承UIObject，并且必须实现UIObject中的构造方法
    /// 可以在子类的构造方法中设置UIType和sortringOrder
    /// 在Init方法中，进行空间查找及一次性的静态空间属性设置
    /// 在Update方法中，设置动态的空间属性
    /// updateLastUI为true时，Finish会自动调用上一个页面的Update方法进行页面更新
    /// </summary>
    public class UIObject
    {
        /// <summary>
        /// UI Unity对象
        /// 在子类中只可访问，不要修改
        /// </summary>
        protected GameObject gameObject = null;
        /// <summary>
        /// 打开UI时传入的数据
        /// 可根据需求进行强转
        /// </summary>
        protected UIData data = null;

        /// <summary>
        /// UIType
        ///  Window      展示Window UI时，会把上一个Window类型的UI及其上层Pop全部隐藏。
        ///  Pop         展示Pop UI时，不会隐藏任何UI
        /// </summary>
        protected UIType type = UIType.Window;

        /// <summary>
        /// UI层级
        /// </summary>
        protected int sortingOrder = 1;

        /// <summary>
        /// LaunchChildAsync LaunchChild创建的UI 为true
        /// </summary>
        private bool isChild = false;

        /// <summary>
        /// LaunchChildAsync LaunchChild创建的UI 为父页面
        /// </summary>
        protected UIObject parent = null;

        /// <summary>
        /// 是否可见
        /// </summary>
        private bool active = true;

        /// <summary>
        /// UI生命周期类型
        /// UI栈 A->B
        /// B为 Normal， 当打开SingleTopUI A 页面时，B会被销毁
        /// B为 Persistent， 当打开SingleTopUI A 页面时，B不会被销毁
        /// </summary>
        protected UILifeType lifeType = UILifeType.Normal;

        /// <summary>
        /// UI所有子页面
        /// </summary>
        protected List<UIObject> children = null;
        public UIData Data { get => data; set => data = value; }
        public GameObject GameObject { 
            get => gameObject; 
            set 
            { 
                gameObject = value;
                SetActive(active);
            } 
        }

        /// <summary>
        /// 关闭时是否Update上一个UI页面
        /// </summary>
        protected bool updateLastUI = false;

        public UIType Type { get => type; }
        public int SortingOrder { get => sortingOrder; }
        public bool Active { get => active; }
        public UILifeType LifeType { get => lifeType; }

        private bool firstUpdate = true;
        protected bool FirstUpdate { get => firstUpdate; }


        public UIObject()
        {
        }

        /// <summary>
        /// 构造方法
        /// 可配置字段：type sortingOrder lifeType
        /// </summary>
        /// <param name="data"></param>
        public UIObject(UIData data)
        {
            this.data = data;
        }

        /// <summary>
        /// 设置可见性
        /// </summary>
        /// <param name="value"></param>
        public void SetActive(bool value)
        {
            active = value;
            if (gameObject != null)
            {
                gameObject.SetActive(value);
            }
        }

        public void Show()
        {
            SetActive(true);
            OnShow();
        }

        public void Hide()
        {
            OnHide();
            SetActive(false);
        }

        public void RestoreActive()
        {
            SetActive(active);
        }

        /// <summary>
        /// 关闭页面
        /// 若updateLastUI=true，执行上一个页面的Update
        /// </summary>
        public void Finish()
        {
            if (!isChild)
            {
                UIManager.Instance.Finish(this, updateLastUI);
            } else
            {
                OnFinished();
                OnDestroy();
                AssetsUtility.Release(gameObject);
                if (updateLastUI)
                {
                    parent.Update();
                }
            }
        }

        public bool CheckValid()
        {
            return gameObject != null;
        }

        /// <summary>
        /// 初始化
        /// 在gameObject创建成功后仅执行一次
        /// </summary>
        public virtual void Init()
        {
        }

        public void FinishFirstUpdate()
        {
            firstUpdate = false;
        }

        /// <summary>
        /// 更新页面
        /// 在gameObject创建成功后执行一次
        /// </summary>
        public virtual void Update()
        {

        }

        public virtual void OnShow()
        {

        }

        public virtual void OnHide()
        {

        }

        /// <summary>
        /// 注册消息
        /// </summary>
        /// <param name="key"></param>
        /// <param name="callback"></param>
        public void RegisterNotification(int key, Action<INotificationData> callback)
        {
            NotificationManager.Register(this, key, callback);
        }

        /// <summary>
        /// 关闭页面回调
        /// </summary>
        public virtual void OnFinished()
        {
            if (children != null)
            {
                for (int index = 0; index < children.Count; index++)
                {
                    children[index].OnFinished();
                }
            }
        }

        /// <summary>
        /// 页面被销毁时回调
        /// 自动销毁注册的消息
        /// </summary>
        public virtual void OnDestroy()
        {
            NotificationManager.Remove(this);
            if (children != null)
            {
                for (int index = 0; index < children.Count; index++)
                {
                    children[index].OnDestroy();
                }
            }
        }

        /// <summary>
        /// 同步创建子页面
        /// </summary>
        /// <param name="path">UI Prefab的路径</param>
        /// <param name="data">UI页面数据</param>
        /// <param name="rootObject">页面父节点</param>
        /// <returns></returns>
        protected UIObject LaunchChild(string path, UIData data = null, GameObject rootObject = null)
        {
            if (children == null)
            {
                children = new List<UIObject>();
            }

            if (rootObject == null)
            {
                rootObject = gameObject;
            }

            if (data == null)
            {
                data = new UIData();
            }
            data.Name = path;

            UIObject uiObject = UIManager.Instance.CreateUIObject(path, data, rootObject, false);
            uiObject.isChild = true;
            uiObject.parent = this;
            uiObject.SetActive(true);
            children.Add(uiObject);
            return uiObject;
        }
        /// <summary>
        /// 异步创建子页面
        /// </summary>
        /// <param name="path">UI Prefab的路径</param>
        /// <param name="data">UI页面数据</param>
        /// <param name="rootObject">页面父节点</param>
        /// <returns></returns>
        protected UIObject LaunchChildAsync(string path, UIData data = null, GameObject rootObject = null)
        {
            if (children == null)
            {
                children = new List<UIObject>();
            }
            if (rootObject == null)
            {
                rootObject = gameObject;
            }

            if (data == null)
            {
                data = new UIData();
            }
            data.Name = path;

            UIObject uiObject = UIManager.Instance.CreateUIObjectAsync(path, data, rootObject, null, false);
            uiObject.isChild = true;
            uiObject.parent = this;
            uiObject.SetActive(true);
            children.Add(uiObject);
            return uiObject;
        }
    }
}

